<!DOCTYPE html>
<html ng-app="DelacorteNumbersApp">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js"></script>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta charset="UTF-8">
    <title>Delacorte Numbers - Al Zimmermann's Programming Contests</title>

    <script>

"use strict";



angular.module('DelacorteNumbersApp', [])
  .controller('DelacorteNumbersController', ['$scope', function($scope) {
    $scope.log = [];
    var workers = [];

    function log(event) {
      $scope.log.unshift(new Date().toLocaleTimeString() + '   ' + event);
    }

    log('Opened application.');

    function setupWorkers(index) {
      workers[index] = new Worker("DelacorteNumbers.js");
      workers[index].onmessage = function(oEvent) {
        var solution = $scope.solutions[oEvent.data.n - 3];
        if (oEvent.data.type === 'PROGRESS') {
          solution.progress = oEvent.data.progress;
        } else {
          if (oEvent.data.type === 'MAX') {
            log('n(' + solution.n + ') MAX found.   old(' + solution.maxD + ') new(' + oEvent.data.dn + ') improvement(' + (oEvent.data.dn - solution.maxD) + ')');
            solution.maxD = oEvent.data.dn;
            solution.maxSquare = oEvent.data.square;
          } else {  //MIN
            log('n(' + solution.n + ') MIN found.   old(' + solution.minD + ') new(' + oEvent.data.dn + ') improvement(' + (solution.minD - oEvent.data.dn) + ')');
            solution.minD = oEvent.data.dn;
            solution.minSquare = oEvent.data.square;
          }
          saveSolutions($scope.solutions);
        }
        $scope.$apply("$scope.solutions");  //TODO is there a way for clean deap object inspection?
      }
    }

    var getSolutions = function() {
      log('Retrieving solutions from database.');

      var solutions = JSON.parse(localStorage.getItem('DelacorteNumbersSolutions'));

      if (!solutions) {
        solutions = [];
        for (var i = 3; i <= 27; ++i) {
          solutions.push({
            n: i,
            nSquared: Math.pow(i, 2),
            minD: Number.MAX_SAFE_INTEGER,
            maxD: Number.MIN_SAFE_INTEGER,
            minSquare: '',
            maxSquare: ''
          });
        }
      }

      for (var i = 0; i < solutions.length; ++i) {
        delete solutions[i].progress;
        delete solutions[i].isRunning;
        delete solutions[i].$$hashKey;
      }

      return solutions;
    }

    var saveSolutions = function(solutions) {
      log('Saving solutions to database.');
      localStorage.setItem('DelacorteNumbersSolutions', JSON.stringify(solutions));
    }

    $scope.run = function(index) {
      var solution = $scope.solutions[index]
      solution.isRunning = true;
      log('Starting search for n(' + solution.n + ')');
      if (!workers[index]) {
        setupWorkers(index);
      }
      workers[index].postMessage(solution);
    }

    $scope.stop = function(index) {
      var solution = $scope.solutions[index]
      solution.isRunning = false;
      log('Stopping search for n(' + solution.n + ')');
      if (workers[index]) {
        workers[index].terminate();
        workers[index] = null;
      }
    }

    $scope.solutions = getSolutions();
    saveSolutions($scope.solutions);
  }]);

    </script>



    <style>

body {font-family: sans-serif;margin: 0;background: #263238;}

th {font-weight: normal;text-align: left;}
td {vertical-align: top;}
td:last-child {font-size: .2em;font-family:"Gill Sans MT";}
td:first-child{white-space:nowrap;}

#log {max-height: 300px;overflow: auto;}
#raw {border-collapse: collapse;}
#log,#raw{margin:15px;background:#fff;box-shadow: 2px 2px 2px 2px #666;}

tr:nth-child(odd),.event:nth-child(odd) {background: #eee;}
.event,td{padding:3px;}
.header,th{background: #09c;color: #fff;padding:5px;}

.start{color:green;}
.stop{color:red;}

.showOnlyRunning{font-size:.8em;color:#ddd;float:right;}

    </style>
  </head>



  <body ng-controller="DelacorteNumbersController" ng-controller="DelacorteNumbersController">
    <div id="log">
      <div class='header'>Log</div>
      <div class="event" ng-repeat="event in log track by $index">{{event}}</div>
    </div>
    <table id="raw">
      <thead>
        <tr>
          <th colspan="2">n</th>
          <th>D#</th>
          <th>
            Square
            <span class="showOnlyRunning">
              [
              <label for="cbShowRunningOnly">show only running</label>
              <input id="cbShowRunningOnly" type="checkbox" ng-model="showRunningOnly">
              ]
            </span>
          </th>
        <tr>
      </thead>
      <tbody ng-repeat="sol in solutions" ng-show="sol.isRunning || !showRunningOnly">
        <tr>
          <td rowspan="2">
            <span>{{sol.n}}</span>
            <span ng-show="sol.progress > 0">[{{sol.progress}}]</span>
            <span class="start" ng-hide="sol.isRunning" ng-click="run($index, sol.n)">&#x25b6;</span>
            <span class="stop" ng-show="sol.isRunning" ng-click="stop($index, sol.n)">&#x25fc;</span>
          </td>
          <td>MIN</td>
          <td>{{sol.minD}}</td>
          <td>{{sol.minSquare}};</td>
        </tr>
        <tr>
          <td>MAX</td>
          <td>{{sol.maxD}}</td>
          <td>{{sol.maxSquare}};</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>